package com.piece.admin.service;

import com.piece.admin.model.TbSysJob;
import com.piece.admin.repository.TbSysJobRepository;
import com.piece.core.framework.enums.StatusType;
import com.piece.core.jpa.repository.BaseService;
import com.piece.core.framework.util.basic.SpringUtil;
import com.piece.core.framework.util.string.StringUtil;
import com.piece.core.framework.util.schedule.ScheduleJob;
import com.piece.core.framework.util.schedule.ScheduleUtil;
import org.quartz.Scheduler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.PostConstruct;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;

@Service
@Transactional
public class TbSysJobService extends BaseService<TbSysJob, String> {

    @Autowired
    private Scheduler scheduler;

    @Autowired
    private TbSysJobRepository tbSysJobRepository;

    @PostConstruct
    public void initRepository() {
        setRepository(tbSysJobRepository);
    }

    @Override
    public TbSysJob insertOrUpdate(TbSysJob job) throws Exception {
        if (null == job.getJobId()) {
            return this.insert(job);
        }

        this.update(job);
        return job;
    }

    @Override
    public TbSysJob insert(TbSysJob job) {
        String status = job.getStatus();
        if (StringUtil.isEmpty(status)) {
            job.setStatus(StatusType.PAUSE.getCode());
        }
        tbSysJobRepository.insert(job);
        ScheduleUtil.createScheduleJob(scheduler, transToScheduleJob(job));
        return job;
    }

    @Override
    public void update(TbSysJob job) {
        String status = job.getStatus();
        if (StringUtil.isEmpty(status)) {
            job.setStatus(StatusType.PAUSE.getCode());
        }
        tbSysJobRepository.update(job);
        ScheduleUtil.updateScheduleJob(scheduler, transToScheduleJob(job));
    }

    @Override
    public void delete(Serializable id) throws Exception {
        TbSysJob job = findById(id);
        ScheduleUtil.deleteJob(scheduler, job.getJobName(), job.getJobGroup());
        delete(job);
    }

    /**
     * 所有执行状态的任务
     */
    public List<TbSysJob> findByRunJobs() {
        HashMap<String, Object> condition = new HashMap<>();
        condition.put("status", StatusType.RUN.getCode());
        return findByCondition(condition);
    }

    /**
     * 任务调度状态修改
     */
    public void changeStatus(TbSysJob job) {
        String status = job.getStatus();
        if (StatusType.RUN.getCode().equals(status)) {
            resumeJob(job);
        }
        else if (StatusType.PAUSE.getCode().equals(status)) {
            pauseJob(job);
        }
        tbSysJobRepository.update(job);
    }

    private void resumeJob(TbSysJob job) {
        ScheduleUtil.resumeJob(scheduler, job.getJobName(), job.getJobGroup());
    }

    private void pauseJob(TbSysJob job) {
        ScheduleUtil.pauseJob(scheduler, job.getJobName(), job.getJobGroup());
    }

    public void run(TbSysJob job) {
        ScheduleUtil.run(scheduler, transToScheduleJob(job));
    }

    public boolean checkJobNameUniq(Long jobId, String jobName) {
        HashMap<String, Object> condition = new HashMap<>();
        condition.put("jobName", jobName);
        if (null != jobId) {
            condition.put("Q_jobId_L_NEQ", jobId);
        }
        List<TbSysJob> jobList = findByCondition(condition);
        return jobList.size() <= 0;
    }

    public boolean checkJobGroupUniq(Long jobId, String jobGroup) {
        HashMap<String, Object> condition = new HashMap<>();
        condition.put("jobGroup", jobGroup);
        if (null != jobId) {
            condition.put("Q_jobId_L_NEQ", jobId);
        }
        List<TbSysJob> jobList = findByCondition(condition);
        return jobList.size() <= 0;
    }

    /**
     * 判断表达式有效性
     */
    public boolean checkCronExpression(String cronExpression) {
        return ScheduleUtil.isValid(cronExpression);
    }

    public ScheduleJob transToScheduleJob(TbSysJob job) {
        ScheduleJob scheduleJob = new ScheduleJob(job.getJobGroup(), job.getJobName(), job.getCronExpression(), job.getMisfirePolicy(), job.getMethodParam());
        String temp[] = job.getMethodName().split("\\.");
        String className = temp[0];
        String methodName = temp[1];
        scheduleJob.setTarget(SpringUtil.getBean(className));
        scheduleJob.setMethod(methodName);
        scheduleJob.setStatus(job.getStatus());
        scheduleJob.setRetryCount(job.getRetryCount());
        scheduleJob.setRetryInterval(job.getRetryInterval());
        return scheduleJob;
    }
}
